package com.hns.can.service.service;

import java.math.BigDecimal;
import java.util.*;

import com.hns.can.base.entity.SysCodeDscEntity;
import com.hns.can.base.entity.SysUserEntity;
import com.hns.can.common.aop.orgTree.LeftOrgAnnotation;
import com.hns.can.master.entity.BaseEqmtInfoEntity;
import com.hns.can.master.upgrade.UpgradeProcessor;
import com.hns.can.service.entity.BaseElectFencCarRelEntity;
import com.hns.can.service.vo.ElectFencGpsSimpleVo;
import com.hns.can.service.vo.ElectFencSetCommandVo;
import com.hns.can.service.vo.ElectFencSetParamsVo;
import com.hns.can.service.vo.ElectFencSimpleVo;
import com.hns.frame.enumrate.EnabledSt;
import com.hns.frame.enumrate.MsgType;
import com.hns.frame.exception.BusinessException;
import com.hns.tool.pub.GpsCorrect;
import com.hns.tool.pub.JsonUtil;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hns.can.common.constants.GlobalConst;
import com.hns.can.common.domain.ReturnResult;
import com.hns.can.common.formula.FillCodeDscValue;
import com.hns.can.common.formula.FillParamsVo;
import com.hns.can.common.service.BaseInfoValueService;
import com.hns.can.service.entity.BaseElectFencEntity;
import com.hns.can.service.entity.BaseElectFencGpsInfoEntity;
import com.hns.can.service.enumrate.FencType;
import com.hns.frame.mybatis.Pagination;
import com.hns.frame.service.CommonService;
import com.hns.tool.pub.DataUtil;
import com.hns.tool.pub.PubUtil;

/**
 * 电子围栏service
 * @author:Fisher
 * @email:zhuangcaijin@126.com
 * @version Revision 2.0.0
 */
@Service
public class ElectFencSetService extends CommonService {
    
    @Autowired
    private FillCodeDscValue codeDscValue;
    
    @Autowired
    private BaseInfoValueService baseInfoValueService;

    @Autowired
    private TaskExecutor taskExecutor;
    
    /**
     * 电子围栏查询
     * @param entity
     * @return
     * @throws Exception
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    public Pagination searchElectFenc(BaseElectFencEntity entity) throws Exception {
        Pagination page = this.myBatisPage("electFenc.searchElectFencCount", 
            "electFenc.searchElectFenc", entity, BaseElectFencEntity.class);
        fillElectFenc(page.getData());
        return page;
    }
    
    /**
     * 导出
     * @param entity
     * @return
     * @throws Exception
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    @SuppressWarnings({"unchecked" })
    public List<BaseElectFencEntity> exportElectFenc(BaseElectFencEntity entity) throws Exception {
        List list = PubUtil.convertListMapToObject(sqlMapDao.selectList("electFenc.searchElectFenc", entity), BaseElectFencEntity.class);
        fillElectFenc(list);
        return list;
    }
    
    private void fillElectFenc(List list) throws Exception {
        //转化生成线路名称
        Map<String,String> map;
        //转化生成机构名称
        map = new HashMap<String,String>();
        map.put("organName",  GlobalConst.DEFAULT_CACHE_VALUE);
        FillParamsVo fillVo1 = new FillParamsVo("organId", map);
        codeDscValue.fillInfoValue(list,new String[] {
            GlobalConst.CACHE_KEY_BASE_ORGAN}, fillVo1);
        Map<String, String> mapTmp = new HashMap<String, String>();
        mapTmp.put("fencType", "CAT00000");
        mapTmp.put("funcType", "FEN00000");
        codeDscValue.fillCodeDscValue(list, mapTmp);
    }

    /**
     * 添加电子围栏
     *
     * @param entity
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    @Transactional
    public Object saveElectFenc(BaseElectFencEntity entity) {
        String jpql = "select o from SysCodeDscEntity o where o.codeValue= ?1 ";
        SysCodeDscEntity sysCodeDscEntity = commonEntityDao.findOneByJpql(jpql, new Object[]{entity.getCityId()});
        if (sysCodeDscEntity == null || PubUtil.isEmpty(sysCodeDscEntity.getRemark())) {
            throw new BusinessException(MsgType.WARN.getFlag(), "该城市未维护区号。");
        }
        
        //生成围栏编号
        String remark = sysCodeDscEntity.getRemark();
        if (remark.length() < 4) {
            remark = "0" + remark;
        }
        Map map = new HashMap();
        map.put("cityId", entity.getCityId());
        String fencCd = (String) sqlMapDao.selectOne("electFenc.getMaxFencCd", map);
        //创建停车场编号
        if (PubUtil.isEmpty(fencCd)) {
            fencCd = new String(remark + "0001");
        } else {
            fencCd = fencCd.substring(4);
            Integer newCd = new Integer(fencCd);
            newCd += 1;
            String str = String.valueOf(newCd);
            str = "0000" + str;
            fencCd = new String(remark + str.substring(str.length() - 4));
        }
        entity.setFencCd(fencCd);
        
        entity.setFencId(DataUtil.sequenceID());
        entity.setUpdateUser(this.getCurrentUser().getUser().getId());
        entity.setCorpId(this.getCurrentUser().getUser().getCorpId());
        entity.setUpdateTime(new Date());
//        entity.setFuncType("FEN00001");
        
        //保存围栏对应的经纬度
        if (PubUtil.isNotEmpty(entity.getList())) {
            for (BaseElectFencGpsInfoEntity gps : entity.getList()) {
                gps.setGpsId(DataUtil.sequenceID());
                gps.setFencId(entity.getFencId());
                commonEntityDao.save(gps);
            }
        }
        commonEntityDao.save(entity);

        //@xujf@info(返回数据)
        String msg = "";
        if ("FEN00001".equals(entity.getFuncType())) {//电子围栏
            msg = "新增电子围栏成功,编号为：" + fencCd;
        } else if ("FEN00002".equals(entity.getFuncType())) {//黑点围栏
            msg = "地图区域设置成功！";
        }
        else if ("FEN00003".equals(entity.getFuncType())) {//黑点围栏
            msg = "新增投币机围栏成功,编号为：" + fencCd;
        }
        return new ReturnResult(msg, entity);
    }

    /**
     * 删除电子围栏
     * @param fencId
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    @Transactional
    public void deleteBaseElectFenc(String fencId) {
        commonEntityDao.delete(BaseElectFencEntity.class, new String[]{fencId});
    }

    /**
     * 更新电子围栏
     *
     * @param entity
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    @Transactional
    public void updateBaseElectFenc(BaseElectFencEntity entity) {
        //先删除原来的围栏经纬度信息
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("fencId", entity.getFencId());
        this.commonEntityDao.deleteByParamsIgnoreNullValue(BaseElectFencGpsInfoEntity.class, paramMap);

        //保存新的经纬度信息
        if (PubUtil.isNotEmpty(entity.getList())) {
            for (BaseElectFencGpsInfoEntity gps : entity.getList()) {
                gps.setGpsId(DataUtil.sequenceID());
                gps.setFencId(entity.getFencId());
                commonEntityDao.save(gps);
            }
        }

        //更新新的信息
        BaseElectFencEntity oldEntity = (BaseElectFencEntity) commonEntityDao.find(entity.getFencId(), BaseElectFencEntity.class);
        
        String[] paramArr = {"fencId","corpId","fencCd","provinceId","cityId"};
        try {
            PubUtil.copyPropertiesInclude(oldEntity, entity, paramArr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        entity.setUpdateUser(this.getCurrentUser().getUser().getId());
        entity.setUpdateTime(new Date());

        commonEntityDao.update(entity);
    }

    /**
     * 根据围栏ID获取多边形围栏各各点坐标
     * @param fencId
     * @return
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    public BaseElectFencEntity getBaseElectFencById(String fencId) throws Exception {
        HashMap<String,String> map = new HashMap<String,String>();
        map.put("fencId",fencId);
        List<BaseElectFencEntity> efList = PubUtil.convertListMapToObject(sqlMapDao.selectList("electFenc.getBaseElectFencEntityById", map), BaseElectFencEntity.class);
        BaseElectFencEntity entity = efList.get(0);
        List electFencEntities = new ArrayList<BaseElectFencEntity>();
        electFencEntities.add(entity);
        fillElectFenc(electFencEntities);
        //如果是多边形，获取多边形的各点坐标
        if(FencType.POLYGON.getFlag().equals(entity.getFencType())){
            BaseElectFencGpsInfoEntity gpsInfo = new BaseElectFencGpsInfoEntity();
            gpsInfo.setFencId(fencId);
            List list = PubUtil.convertListMapToObject(sqlMapDao.selectList("baseElectFencGpsInfo.searchBaseElectFencGpsInfo", gpsInfo), BaseElectFencGpsInfoEntity.class);
            entity.setList(list);
        }
        return entity;
    }

    /**
     * 分页查询电子围栏与车辆关系
     * @param vo
     * @author:zhangzq
     * @email:
     */
    @Transactional
    @LeftOrgAnnotation()
    public Pagination searchElectFencCarRel(ElectFencSetParamsVo vo) throws Exception {
        Pagination page = this.myBatisPage("baseElectFencCarRel.searchElectFencCarRelCount",
                "baseElectFencCarRel.searchElectFencCarRel", null, BaseElectFencCarRelEntity.class);
        baseInfoValueService.fillOrganLineLicPltNo(page.getData());
        return page;
    }

    /**
     * 根据车辆ID查询电子围栏与车辆关系
     * @param carId
     * @author:zhangzq
     * @email:
     */
    public List<BaseElectFencCarRelEntity> searchElectFencCarRelByCarId(String carId) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("carId", carId);
        params.put("relSt", "1");
        params.put("corpId",this.getCurrentUser().getUser().getCorpId());
        List list = PubUtil.convertListMapToObject(sqlMapDao.selectList("baseElectFencCarRel.searchElectFencCarRelByCarId", params), BaseElectFencCarRelEntity.class);
        return list;
    }

    /**
     * 下发电子围栏命令
     * @param vo
     * @author:zhangzq
     * @email:
     */
    @Transactional
    @LeftOrgAnnotation()
    public void setElectFenc(ElectFencSetParamsVo vo) throws Exception {
        //检验电子围栏是否在绑定中
        checkForElectFencCarRel(vo);
        //删除绑定超时30分钟电子围栏
        delTimeOutOfElectFencCarRel(vo);
        //填充电子围栏完整信息
        List<BaseElectFencEntity> oriElectFencList = vo.getElectFencList();
        List<BaseElectFencEntity> electFencList = new ArrayList<BaseElectFencEntity>();
        for(BaseElectFencEntity entity :oriElectFencList ){
            BaseElectFencEntity obj = getBaseElectFencById(entity.getFencId());

            obj.setDriveDrc(entity.getDriveDrc());
            electFencList.add(obj);
        }
        //下发电子围栏命令
        List<String> carIdList = vo.getOrgIds();
        for(String carId : carIdList){
            String eqmtCd = getEqmtCd(carId);
            if(PubUtil.isNotEmpty(eqmtCd)){
                ElectFencSetCommandVo commandVo = new ElectFencSetCommandVo();
                commandVo.setDevId(eqmtCd);
                commandVo.setCarId(carId);
                //保存电子围栏与车辆关系
                saveBaseElectFencCarRel(commandVo,electFencList);
                //给通信下发电子围栏命令
                assembleElectFencSetCommandVo(commandVo, electFencList);
                String commandStr = JsonUtil.getJsonStringFromObject(commandVo);
                UpgradeProcessor processor = new UpgradeProcessor("1E",commandStr,taskExecutor);
//                processor.process();
            }
        }

    }

    /**
     * 组装下发电子围栏命令
     * @param commandVo
     * @param electFencList
     * @author:zhangzq
     * @email:
     */
    private void assembleElectFencSetCommandVo(ElectFencSetCommandVo commandVo,List<BaseElectFencEntity> electFencList){
        for(BaseElectFencEntity item :electFencList ){
            ElectFencSimpleVo vo1 = new ElectFencSimpleVo();
            PubUtil.copyProperties(item,vo1);
//            vo1.setCoreLgt(item.getCoreLgt());
//            vo1.setCoreLtt(item.getCoreLtt());
//            vo1.setCoreRadius(item.getCoreRadius());
            
            if(FencType.POLYGON.getFlag().equals(item.getFencType())){
                List<BaseElectFencGpsInfoEntity> gpsList = item.getList();
                if(PubUtil.isNotEmpty(gpsList)){
                    for (BaseElectFencGpsInfoEntity gps : gpsList) {
                        ElectFencGpsSimpleVo vo2=new ElectFencGpsSimpleVo();
                        Double lat, lon;
                        lon = gps.getFencLgt().doubleValue();
                        lat = gps.getFencLtt().doubleValue();
                        double[] result=GpsCorrect.gcj2wgs(lat,lon);
//                        GpsCorrect.gcj_decrypt_exact(lat,lon);
//                        PubUtil.copyProperties(gps,vo2);
                        vo2.setFencLgt(BigDecimal.valueOf(result[1]));
                        vo2.setFencLtt(BigDecimal.valueOf(result[0]));
                        vo1.getGpsList().add(vo2);
                    }
                }
            }else if(FencType.CIRCLE.getFlag().equals(item.getFencType())){
            	if(PubUtil.isNotEmpty(item.getCoreLgt()) && PubUtil.isNotEmpty(item.getCoreLtt())){
                	double[] result=GpsCorrect.gcj2wgs(item.getCoreLtt().doubleValue(),item.getCoreLgt().doubleValue());
                    vo1.setCoreLgt(BigDecimal.valueOf(result[1]));
                    vo1.setCoreLtt(BigDecimal.valueOf(result[0]));
                }
            }
            commandVo.getElectFencList().add(vo1);
        }
    }

    /**
     * 下发电子围栏解绑命令
     * @param vo
     * @author:zhangzq
     * @email:
     */
    public void unsetElectFenc(ElectFencSetParamsVo vo) throws Exception {
        //下发电子围栏命令
        List<String> carIdList = vo.getOrgIds();
        for(String carId : carIdList){
            String eqmtCd = getEqmtCd(carId);
            if(PubUtil.isNotEmpty(eqmtCd)){
                ElectFencSetCommandVo commandVo = new ElectFencSetCommandVo();
                commandVo.setDevId(eqmtCd);
                commandVo.setCarId(carId);
                //给通信下发电子围栏命令
                String commandStr = JsonUtil.getJsonStringFromObject(commandVo);
                UpgradeProcessor processor = new UpgradeProcessor("1E",commandStr,taskExecutor);
                processor.process();
            }
        }

    }

    /**
     * 检验电子围栏是否在绑定中
     * @param vo
     * @author:zhangzq
     * @email:
     */
    @LeftOrgAnnotation()
    @Transactional
    private void checkForElectFencCarRel(ElectFencSetParamsVo vo)throws Exception {
        Integer count = (Integer) sqlMapDao.selectOne("baseElectFencCarRel.checkElectFencCarRel",null);
        if(PubUtil.isNotEmpty(count) && count > 0){
            throw new BusinessException(MsgType.WARN.getFlag(),"车辆正在绑定电子围栏，请稍后再操作");
        }
    }

    /**
     * 删除绑定超时30分钟电子围栏
     * @param vo
     * @author:zhangzq
     * @email:
     */
    @LeftOrgAnnotation()
    @Transactional
    private void delTimeOutOfElectFencCarRel(ElectFencSetParamsVo vo)throws Exception {
        sqlMapDao.selectOne("baseElectFencCarRel.delElectFencCarRel",null);
    }

    /**
     * 保存电子围栏与车辆关系
     * @param commandVo
     * @author:zhangzq
     * @email:
     */
    @Transactional
    private void saveBaseElectFencCarRel(ElectFencSetCommandVo commandVo,List<BaseElectFencEntity> electFencList){
        for(BaseElectFencEntity item :electFencList ){
            BaseElectFencCarRelEntity entity =  new BaseElectFencCarRelEntity();
            entity.setRelId(DataUtil.sequenceID());
            entity.setEqmtCd(commandVo.getDevId());
            entity.setCarId(commandVo.getCarId());
            entity.setFencId(item.getFencId());
            entity.setDriveDrc(item.getDriveDrc());
            entity.setCrtUser(this.getCurrentUser().getUser().getId());
            entity.setCrtTime(new Date());
            entity.setIssuedSt("UPSM0101");
            entity.setRelSt("2");
            commonEntityDao.save(entity);
        }
    }

    /**
     * 根据车辆ID获取设备编码
     * @param carId
     * @author:zhangzq
     * @email:
     */
    private String getEqmtCd(String carId){
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("rltvCarId", carId);
        params.put("enabledSt", EnabledSt.ENABLE.getFlag());
        String jpql="select o from BaseEqmtInfoEntity o where o.rltvCarId= ?1 and o.enabledSt= ?2 ";
        BaseEqmtInfoEntity entity = commonEntityDao.findOneByJpql(jpql,new Object[]{carId,EnabledSt.ENABLE.getFlag()});
        if(PubUtil.isNotEmpty(entity)){
            return entity.getEqmtCd();
        }
        return "";
    }

}
